package com.ll.utils;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.digest.DigestUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
 * 负责处理加密、解密、生成签名等操作
 * @author sunhuaili
 *
 */
public class CryptoUtils {
	
	private static final Logger LOG = LoggerFactory.getLogger(CryptoUtils.class);
	
	public static final byte[] encryptUse3DES(byte[] key, byte[] content) {
		return des3(key,content,Cipher.ENCRYPT_MODE);
	}
	/**
	 * 采用3DES进行解密处理，系统中暂时未使用
	 * @param key 秘钥
	 * @param ciphertext  密文
	 * @return
	 */
	public static final byte[] decryptUse3DES(byte[] key,byte[] ciphertext) {
		return des3(key,ciphertext,Cipher.DECRYPT_MODE);
	}
	/**
	 * 用AES进行加密
	 * @param key 秘钥
	 * @param content 加密内容
	 * @return
	 */
	public static final byte[] encryptUseAes(byte[] key,byte[] content){
		return aes(key,content,Cipher.ENCRYPT_MODE);
	}
	/**
	 * 用AES进行解密
	 * @param key
	 * @param ciphertext
	 * @return
	 */
	public static final byte[] decryptUseAes(byte[] key,byte[] ciphertext){
		return aes(key,ciphertext,Cipher.DECRYPT_MODE);
	}
	
	/**
	 * 3DES加密和解密
	 * @param key 秘钥
	 * @param text 加密和解密的内容
	 * @param mode 加解密模式，
	 * @return 
	 */
	private static final byte[] des3(byte[] key,  byte[] text,
			int mode) {
		// 计算key，3DES要求key的位数为24位，将key位数补齐，node端采用同样的规则
		// 如果位数不够，需要补齐
		byte[] tmpkey = alignToLen(key,24);
		try {
			SecretKey secretKey = new SecretKeySpec(tmpkey, "DESede");
			Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");
			cipher.init(mode, secretKey);
			return cipher.doFinal(text);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * byte数组对齐
	 * @param original 原始的数组
	 * @param len 对齐之后的数字长度
	 * @return
	 */
	private static final byte[] alignToLen(byte[] original , int len){
		byte[] tmpkey = new byte[len];
		for (int i = 0; i < tmpkey.length; i++) {
			if (i < original.length) {
				tmpkey[i] = original[i];
			} else {
				tmpkey[i] = 0;
			}
		}
		return tmpkey;
	}
	
	
	/**
	 * 用md5取数字签名
	 * @param key  秘钥
	 * @param content 获取摘要的内容
	 * @return
	 */
	public static final String createSignature(String key,String content){
		LOG.debug("key:{}",key);
		LOG.debug("content:{}",content);
		if(key == null)
			throw new IllegalArgumentException("秘钥不能为空");
		String signature = DigestUtils.md5Hex(key);
		LOG.debug("first signature:{}",signature);
		if(content == null){//如果内容为空，则只对秘钥进行两次MD5
			content = "";
		}
		signature = DigestUtils.md5Hex(signature+content);
		LOG.debug("second signature:{}",signature);
		return signature;
	}
	
	private static final byte[] aes(byte[] key,byte[] content,int mode){
		if (key == null) {
			throw new RuntimeException("秘钥不能为空");
        }
		key = alignToLen(key,16);
        SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
        Cipher cipher;
		try {
			cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
			cipher.init(mode, skeySpec);
			byte[] encrypted = cipher.doFinal(content);
			return encrypted;
		} catch (Exception e) {
			throw new RuntimeException(e);
		} 
	}
	
	public static void main(String[] args) {
		String sign = CryptoUtils.createSignature("123456", "中华人民共和国");
		System.out.println(sign);
		String sign2 = CryptoUtils.createSignature("123456", "abcdefg");
		System.out.println(sign2);
	}
	
}
